package com.llt.test.thread;

import java.util.Random;
import java.util.concurrent.*;

/**
 * 多线程安全的猜数字游戏
 * @author LLT
 */
public class GuessGame {

    // 猜测请求
    static class Guess {
        String playerName;
        int number;

        public Guess(String playerName, int number) {
            this.playerName = playerName;
            this.number = number;
        }
    }

    // 反馈结果
    static class Result {
        boolean isCorrect;
        boolean isHigher;

        public Result(boolean isCorrect, boolean isHigher) {
            this.isCorrect = isCorrect;
            this.isHigher = isHigher;
        }
    }

    private static final int TARGET = new Random().nextInt(101);
    private static final BlockingQueue<Guess> GUESS_QUEUE = new LinkedBlockingQueue<>();
    private static final ConcurrentHashMap<String, BlockingQueue<Result>> RESULT_MAP = new ConcurrentHashMap<>();
    private static volatile boolean GAME_OVER = false;

    public static void main(String[] args) {
        System.out.println("A: 生成的目标数字是：" + TARGET);

        // A 线程：裁判
        Thread judge = new Thread(() -> {
            try {
                while (!GAME_OVER) {
                    // 阻塞获取
                    Guess guess = GUESS_QUEUE.take();
                    System.out.println(guess.playerName + ": 猜了数字 " + guess.number);

                    if (guess.number == TARGET) {
                        GAME_OVER = true;
                        System.out.println("A: 恭喜 " + guess.playerName + " 猜对了！");
                        RESULT_MAP.get(guess.playerName).put(new Result(true, false));
                    } else if (guess.number > TARGET) {
                        System.out.println("A: " + guess.playerName + " 猜大了！");
                        RESULT_MAP.get(guess.playerName).put(new Result(false, true));
                    } else {
                        System.out.println("A: " + guess.playerName + " 猜小了！");
                        RESULT_MAP.get(guess.playerName).put(new Result(false, false));
                    }
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        // B线程：二分法猜
        Thread b = new Thread(() -> {
            String name = "B";
            RESULT_MAP.put(name, new ArrayBlockingQueue<>(1));
            int low = 0, high = 100;
            try {
                while (!GAME_OVER) {
                    int guess = (low + high) / 2;
                    GUESS_QUEUE.put(new Guess(name, guess));
                    Result result = RESULT_MAP.get(name).take();
                    if (result.isCorrect) {
                        System.out.println(name + ": 猜中啦！");
                        break;
                    }
                    if (result.isHigher) {
                        high = guess - 1;
                    } else {
                        low = guess + 1;
                    }
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        // C线程：随机猜
        Thread c = new Thread(() -> {
            String name = "C";
            RESULT_MAP.put(name, new ArrayBlockingQueue<>(1));
            Random random = new Random();
            try {
                while (!GAME_OVER) {
                    int guess = random.nextInt(101);
                    GUESS_QUEUE.put(new Guess(name, guess));
                    Result result = RESULT_MAP.get(name).take();
                    if (result.isCorrect) {
                        System.out.println(name + ": 猜中啦！");
                        break;
                    }
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        judge.start();
        b.start();
        c.start();
    }
}
